package cn.kmsoft.jssc.controller;

import cn.kmsoft.common.utils.StringUtil;
import cn.kmsoft.jssc.config.AnalyseConfig;
import cn.kmsoft.jssc.entity.analyse.AnalyseTable;
import cn.kmsoft.jssc.entity.analyse.AnalyseTaskParam;
import cn.kmsoft.jssc.entity.analyse.CustomOverlay;
import cn.kmsoft.jssc.entity.analyse.SpatialOverlayParam;
import cn.kmsoft.jssc.service.ParallelAnalyseService;
import cn.kmsoft.jssc.service.SingleAnalyseService;
import cn.kmsoft.wololo.object.query.AnalysisType;
import cn.kmsoft.wololo.object.GeoJson;
import cn.kmsoft.wololo.object.GeoJsonFeature;
import cn.kmsoft.wololo.object.query.GeoJsonQuery;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.http.*;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * 技术审查与空间叠加分析的基础控制类
 *
 * @author : cqwensten
 * @description : todo
 * @email : cqwensten@163.com
 * @date : 2023/1/28
 */
@Slf4j
public class BaseController {
    @Autowired
    protected RedisTemplate redisTemplate;//缓存数据库
    @Autowired
    protected RestTemplate restTemplate;
    @Autowired
    protected AnalyseConfig analyseConfig;

    @Autowired
    private ParallelAnalyseService parallelAnalyseService;
    @Autowired
    private SingleAnalyseService singleAnalyseService;

    @Value("${spring.profiles.active}")
    protected String profilesActive;


    /**
     * 更新RabbtMQ消息队列状态
     *
     * @param projectId   编号
     * @param statusCode   在线时候需要将statusCode=0；
     */
    protected void updRabbitMQStatus(String projectId, int statusCode){
        //在线为online,离线为offline
        ValueOperations ops = redisTemplate.opsForValue();
        ops.set("rabbitmq-statuscode", statusCode);

        String setRabbitMQStatusMsg = String.format("--->updRabbitMQStatus, projectId: %s, statuscode: %d ", projectId, statusCode);
        System.out.println();
        System.out.println(setRabbitMQStatusMsg);
    }

    /**
     * 按projectId设置技术审查的处理状态
     *
     * @param projectId
     * @param value
     */
    protected void setJsscStatusByProjectId(String projectId, String value){
        if(StringUtil.isNullOrEmpty(projectId)){
            return;
        }
        ValueOperations ops = redisTemplate.opsForValue();
        ops.set("jssc-"+projectId, value);

        String setJsscStatusMsg = String.format("--->setJsscStatus2Redis,jssc-%s: %s",projectId, value);
        System.out.println();
        System.out.println(setJsscStatusMsg);
    }


    public JSONObject postApi(String url, String queryJson) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<String> entity = new HttpEntity<>(queryJson, headers);
        ResponseEntity<JSONObject> resEntity = restTemplate.exchange(url, HttpMethod.POST, entity, JSONObject.class);
        return resEntity.getBody();
    }

    /**
     * doOverlayAnalyst-自定义叠加分析，并行计算
     *
     * @param taskId     任务编号（从业务角度用户传入的）
     * @param customParam   空间分析所需参数,包含分析对象表集合analysttables、项目红线GeonJson、任务编号taskId等
     * @return
     */
    public List<CustomOverlay> doOverlayAnalyst(String taskId, SpatialOverlayParam customParam) {
        //结果集合
        List<CustomOverlay> cusOverlayList = null;
        //1-解析参数
        //目标图层表
        List<AnalyseTable> analyseTables = customParam.getAnalyseTables();
        //待叠加的红线范围
        GeoJsonQuery allGeoQuery = customParam.getGeoJsonQuery();// 获取上传的图形
        if (analyseTables == null || analyseTables.size() == 0 || allGeoQuery == null || allGeoQuery.getGeoJson() == null) {
            String msgStr = String.format("--->doOverlayAnalyst canced, taskId: %s, 叠加分析analyseTables或者allGeoQuery为空",taskId);
            System.out.println();
            System.out.println(msgStr);
            log.info(msgStr);

            return cusOverlayList;
        }
        //投影坐标wkid
        int wkid = allGeoQuery.getWkid();
        if(StringUtil.isNullOrEmpty(taskId)) {
            taskId = UUID.randomUUID().toString();
        }

        String msgStr = String.format("--->doOverlayAnalyst started,叠加分析开始!, taskId: %s",taskId);
        System.out.println();
        System.out.println(msgStr);
        log.info(msgStr);

        String analyseType = allGeoQuery.getType().toString().toLowerCase();//包括intersect、spatialquery

        if (allGeoQuery.getGeoJson().trim().startsWith("{")) {
            GeoJson geoJson = (GeoJson) JSONObject.parseObject(allGeoQuery.getGeoJson(), GeoJson.class);
            cusOverlayList = new ArrayList<CustomOverlay>();
            // 3.非常重要，逐个地块进行分析、汇总
            List<GeoJsonFeature> feas = geoJson.getFeatures();
            int feaCount= feas.size();
            for (int i = 0; i < feaCount; i++) {
                GeoJsonFeature fea = feas.get(i);

                int xh = i+1;
                //获取要素的关键属性信息
                Map<String, Object> feaPropers = fea.getProperties();
                String dkbh = feaPropers.get("DKBH") != null ? feaPropers.get("DKBH").toString() : String.valueOf(i+10000) ;
                if (StringUtil.isNullOrEmpty(dkbh)) {
                    // 不参加叠加运算
                    System.out.println(String.format("--->地块编号DKBH为空, 自动分配地块编号为：%s ","地块"+(i+1)));
                    //continue;
                }
                System.out.println();
                System.out.println(String.format("--->第 %d / %d 个地块叠加分析开始,地块编号：%s",xh, feaCount, dkbh));

                /************* 2.上传的地块分为单个地块进行叠加 ***************/
                // 构建单个地块的Feature
                List<GeoJsonFeature> subFeas = new ArrayList<GeoJsonFeature>();
                subFeas.add( feas.get(i) );
                GeoJson dkGeoJson = new GeoJson();
                dkGeoJson.setType( geoJson.getType() );
                dkGeoJson.setFeatures(subFeas);
                String dkJsonStr = JSONObject.toJSONString(dkGeoJson);

                GeoJsonQuery dkQuery = new GeoJsonQuery();
                dkQuery.setDigits(allGeoQuery.getDigits());
                dkQuery.setReturnEllipsoidalArea(allGeoQuery.getReturnEllipsoidalArea());
                dkQuery.setType(allGeoQuery.getType());
                dkQuery.setWkid(allGeoQuery.getWkid());
                dkQuery.setGeoJson(dkJsonStr);

                String jobId = UUID.randomUUID().toString();
                System.out.println(String.format("--->overlayCustom: %s", jobId));
                // 提交分析
                AnalyseTaskParam taskParam = new AnalyseTaskParam(analyseType);
                taskParam.setJobId(jobId);
                taskParam.setTaskId(taskId);
                taskParam.setDkbh(dkbh);
                taskParam.setQuery(dkQuery);
                //taskParam.setDkmj(dkmj);
                taskParam.setWkid(wkid);//项目红线的wkid

                AnalysisType analysisType = allGeoQuery.getType();
                taskParam.setAnalystType(analysisType.toString());

                // 分析结果
                CustomOverlay cusOverlay = this.parallelAnalyseService.submitOverlayCustomAnalyse(analyseType,taskParam, analyseTables);
                cusOverlay.setDkbh(dkbh);
                cusOverlay.setPhase(customParam.getPhase());
                cusOverlay.setUploadFeaPropers(feaPropers);

                cusOverlayList.add(cusOverlay);
                //System.out.println();
                System.out.println(String.format("--->第 %d /%d 个地块叠加分析完毕,地块编号：%s",xh, feaCount, dkbh));
                System.out.println();
            }
            System.out.println();
            System.out.println(String.format("--->doOverlayAnalyst finished,所有地块的叠加分析完成!, taskId: %s",taskId));
            System.out.println();
        }

        return cusOverlayList;
    }
    

    /**
     * 根据 analyseCode获取所有的AnalyseTable
     * @param config
     * @param analyseCode
     * @return
     */
    public List<AnalyseTable> getAnalyseTablesByAnalystCode(AnalyseConfig config, String analyseCode){
        List<AnalyseTable> analyseTables = config.getAllAnalyseTableByAnalystCode(analyseCode);
        return analyseTables;
    }

    /**
     * 根据 analyseCode获取默认的AnalyseTable
     * @param config
     * @param analyseCode
     * @return
     */
    public AnalyseTable getDefaultAnalyseTableByAnalystCode(AnalyseConfig config, String analyseCode){
        String defaultYear = config.getDefaultYearByAnalystCode(analyseCode);
        AnalyseTable analyseTable = config.getAnalyseTableByAnalystCodeAndYear(analyseCode,defaultYear);

        return analyseTable;
    }

    /**
     * 根据 analyseCode和年份获取某一年的AnalyseTable
     *
     * @param config
     * @param analyseCode
     * @param yearStr
     * @return
     */
    public  List<AnalyseTable> getAnalyseTableByAnalystCodeAndYear(AnalyseConfig config, String analyseCode,String yearStr){
        List<AnalyseTable> analyseTableList = new ArrayList<AnalyseTable>();
        AnalyseTable analyseTable = config.getAnalyseTableByAnalystCodeAndYear(analyseCode,yearStr);
        analyseTableList.add(analyseTable);
        return analyseTableList;
    }

    /**
     * 生成空间分析所需的参数，包括图形范围，要分析的数据项列表
     * @param config
     * @param lx  包括base-基础版、advance-高级版、times-时序版
     * @return
     */
    public List<AnalyseTable> getAnalyseTablesByLx(AnalyseConfig config, String lx){
        List<AnalyseTable> analyseTableList = new ArrayList<AnalyseTable>();
        Map<String,String> baseAnalyses = config.getDefaultAnalyses();
        switch (lx){
            case "base": {
                //基础版
                String baseAnalyseCodes = baseAnalyses.get("basepoints");
                String[] baseAnalyseCodes_arr = baseAnalyseCodes.split(",");
                for (String analyseCode : baseAnalyseCodes_arr) {
                    if( !StringUtil.isNullOrEmpty(analyseCode)) {
                        String defaultYear = config.getDefaultYearByAnalystCode(analyseCode);
                        AnalyseTable analyseTable = config.getAnalyseTableByAnalystCodeAndYear(analyseCode, defaultYear);
                        if(analyseTable!=null) {
                            analyseTableList.add(analyseTable);
                        }
                    }
                }

                break;
            }
            case "advance": {
                //高级版
                String advanceAnalyseCodes = baseAnalyses.get("advancepoints");
                String[] advanceAnalyseCodes_arr = advanceAnalyseCodes.split(",");
                for (String analyseCode : advanceAnalyseCodes_arr) {
                    if( !StringUtil.isNullOrEmpty(analyseCode)) {
                        String defaultYear = config.getDefaultYearByAnalystCode(analyseCode);
                        AnalyseTable analyseTable = config.getAnalyseTableByAnalystCodeAndYear(analyseCode, defaultYear);
                        if(analyseTable!=null) {
                            analyseTableList.add(analyseTable);
                        }
                    }
                }
                break;
            }
            case "times": {
                //时序版
                String advanceAnalyseCodes = baseAnalyses.get("timespoints");
                String[] advanceAnalyseCodes_arr = advanceAnalyseCodes.split(",");
                for (String analyseCode : advanceAnalyseCodes_arr) {
                    if( !StringUtil.isNullOrEmpty(analyseCode)) {
                        List<AnalyseTable> analyseTables = config.getAllAnalyseTableByAnalystCode(analyseCode);
                        for (AnalyseTable analyseTable : analyseTables) {
                            analyseTableList.add(analyseTable);
                        }
                    }
                }
                break;
            }
        }

        return analyseTableList;
    }


}
